/***************************************************************************
 * Open Object Oriented ANSI C                                             *
 ***************************************************************************
 * Code given under the terms of GNU General Public Licence (GPLv3)        *
 * and without any waranties of any kind including but not limitative to   *
 * waranties on merchandability or any particular applications fitness.    *
 * For more information on GNU/GPL go on :                                 *
 * "http://www.gnu.org/copyleft/gpl.html"                                  *
 *                                                                         *
 * You are allowed to use it for any purposes in the terms of GNU/GPLv3    *
 * (or more).                                                              *
 * This text MUST stay in state on copyed sources (or sources using it)    *
 * and must not be altered.                                                *
 * You are allowed to add your name at the end of the Copylefs list.       *
 ***************************************************************************
 * Copylefts List :                                                        *
 ***************************************************************************
 * 2010-03-20 Patrick PIGNOL <pignol_patrick@hotmail.com> (Original)       *
 * (Type your name here if needed)                                         *
 ***************************************************************************/
#include <signal.h>
#include "Mem.h"
#include "ExceptionHandler.h"
#include "ExceptionManager.h"

static ExceptionHandlerVirtualTable* ExceptionHandlerVirtualTableInstance = 0;

ExceptionHandler* ExceptionHandlerNew(unsigned long pArgsCount, va_list* pParameters)
{
    ExceptionHandler* this;
    this = malloc(sizeof(ExceptionHandler));
    if(!this)
    {
        raise(SIGABRT); /* (this = 0) ? Error: Ok;*/
    }
    this->VirtualTable = ExceptionHandlerInitialize(this, pArgsCount, pParameters);
    this->Constructor = ExceptionHandlerConstructor;
    this->Destructor = ExceptionHandlerDestructor; /* Destructor pointer of object. Called by Garbage(). Must be propagated on inherited that do not override.*/
    this->Clone = ExceptionHandlerClone;
    this->ExceptionTypeIDHandler = ExceptionHandlerExceptionTypeIDHandler;
    this->Handle = ExceptionHandlerHandle;
    this->Constructor(this, pArgsCount, pParameters);
    return this;
}

ExceptionHandlerVirtualTable* ExceptionHandlerInitialize(ExceptionHandler* this, unsigned long pArgsCount, va_list* pParameters)
{
    if(!ExceptionHandlerVirtualTableInstance)
    {
        ExceptionHandlerVirtualTableInstance = (ExceptionHandlerVirtualTable*) malloc(sizeof(ExceptionHandlerVirtualTable));
        if(!ExceptionHandlerVirtualTableInstance)
        {
            raise(SIGABRT);
        }
        ExceptionHandlerVirtualTableInstance->TypeID = EXCEPTIONHANDLER_TYPEID;
        ExceptionHandlerVirtualTableInstance->Interface = 0;

        ExceptionHandlerVirtualTableInstance-> ReferenceCount = 0;

        ExceptionHandlerVirtualTableInstance->AncestorTable = ClassInitialize((Class*)this, pArgsCount, pParameters);

        ExceptionHandlerVirtualTableInstance->ReferenceCount = 0;

        ExceptionHandlerVirtualTableInstance->new = ExceptionHandlerNew;
        ExceptionHandlerVirtualTableInstance->Initialize = ExceptionHandlerInitialize;
        ExceptionHandlerVirtualTableInstance->Garbage = (void(*)(ExceptionHandler*))ExceptionHandlerVirtualTableInstance->AncestorTable->Garbage;
        ExceptionHandlerVirtualTableInstance->TypeOf = (unsigned long int (*)(ExceptionHandler*))ExceptionHandlerVirtualTableInstance->AncestorTable->TypeOf;
        ExceptionHandlerVirtualTableInstance->IsSameTypeThanTypeID = (bool (*)(ExceptionHandler*, unsigned long int))ExceptionHandlerVirtualTableInstance->AncestorTable->IsSameTypeThanTypeID;
        ExceptionHandlerVirtualTableInstance->IsKindOfTypeID = (bool (*)(ExceptionHandler* this, unsigned long int))ExceptionHandlerVirtualTableInstance->AncestorTable->IsKindOfTypeID;
        ExceptionHandlerVirtualTableInstance->IsSameTypeThan = (bool (*)(ExceptionHandler* this, Class*))ExceptionHandlerVirtualTableInstance->AncestorTable->IsSameTypeThan;
        ExceptionHandlerVirtualTableInstance->IsKindOf = (bool (*)(ExceptionHandler* this, Class*))ExceptionHandlerVirtualTableInstance->AncestorTable->IsKindOf;
    }
    ExceptionHandlerVirtualTableInstance->ReferenceCount++;
    return ExceptionHandlerVirtualTableInstance;
}

void ExceptionHandlerConstructor(ExceptionHandler* this, unsigned long int pArgsCount, va_list* pParameters)
{
    if(pArgsCount > 2)
    {
        this->aExceptionTypeID = va_arg(*pParameters, unsigned long int);
        this->aTargetObject = va_arg(*pParameters, Class*);
        this->aHandler = *va_arg(*pParameters, void (*)(Class*, Exception*, unsigned long int, va_list*));
    }
    else
    {
        ((ExceptionManager*)ExceptionManagerGetInstance())->throw(new((void*(*)(unsigned long int, va_list*))ExceptionNew,1,"ExceptionHandler:\n\tToo few parameters for ExceptionHandler::Constructor."));
    }
}

void ExceptionHandlerDestructor(ExceptionHandler* this)
{
}

ExceptionHandler* ExceptionHandlerClone(ExceptionHandler* this)
{
    ExceptionHandler* vClone = 0;
    vClone = new((void*(*)())ExceptionHandlerNew, this->aExceptionTypeID, this->aTargetObject, this->aHandler);
    return vClone;
}

unsigned long int ExceptionHandlerExceptionTypeIDHandler(ExceptionHandler* this)
{
    return this->aExceptionTypeID;
}

void ExceptionHandlerHandle(ExceptionHandler* this, Exception* pException, unsigned long int pArgsCount, va_list* pParameters)
{
    this->aHandler(this->aTargetObject, pException, pArgsCount, pParameters);
}
